home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / util / libs / MMULib.lha / MMULib / Autodocs / implementation next >
Encoding:
Text File  |  1998-09-27  |  9.9 KB  |  219 lines

  1. Abstract:
  2.     This document describes some of the planned implementation details
  3.     of the mmu.library and the memory.library. Everything is highly
  4.     preliminary and open for discussion.
  5.  
  6. mmu.library:
  7.     The library startup function must check the following:
  8.  
  9. -    which processor is installed and which type of MMU is used. MMU types
  10.     are usually implicit to the CPU type except for the 68851 MMU which has
  11.     to be checked explicitly.
  12.  
  13. -    Scan an already existing MMU table and build an abstraction of that MMU
  14.     table called the global context. 
  15.     This routine is of course processor specific.
  16.     OR, if no MMU table has been build, provide one by scanning the memory
  17.     in the system, using the expansion library for scanning for expansion
  18.     cards. Special hardware that is only present in the later amiga models
  19.     must be checked as well. The detailed procedure can be found in the
  20.     enforcer code.
  21.  
  22. -    Rebuild the library base and the function vectors aligned in some page
  23.     of memory and delete the version that was created by MakeLibrary(). 
  24.     This step requires some meta-magic but must be done to allow the library
  25.     to protect itself from unauthorized access, as for example for a future
  26.     multi user processing.
  27.  
  28. -    Build the MMU tables from the global context and install it.
  29.  
  30.     The MMU library should really build TWO MMU tables, a user table for
  31.     code running in user mode. This is represented by the MMU table of the
  32.     context. And a supervisor MMU table which is identically to the MMU
  33.     table that was found before the library was build.
  34.  
  35.  
  36.     Context switches:
  37.  
  38. To be able to provide individual contexts for each task, the mmu table must
  39. be exchanged on task switch. That can be done either by patching some exec
  40. functions or by setting the tc_Switch/tc_Launch pointers of the task. I
  41. would recommend the second alternative because patches have usually a problem
  42. of their own. Sigh.
  43.  
  44. To be able to access library code safely on a context switch, a user MMU table
  45. and a supervisor MMU table must be build. As the tc_Switch/tc_Launch functions
  46. are executed in supervisor code, they can freely access the library base.
  47.  
  48. Since no data pointer of any kind is available in the task structure (except
  49. a UserData pointer, but that should be available for the user and shouldn't
  50. be used up by the mmu.library), the identification of the "Context" of a
  51. task requires special care. The context structure might look, for example,
  52. like this:
  53.  
  54. struct Context {
  55.         ULONG    ctx_MagicCookie;
  56.         struct Context *ctx_MySelf;        /* for identifcation a pointer to itself */
  57.         .....
  58.         UWORD    ctx_SwitchInst;            /* a 4eb9 - jsr Abs.l */
  59.         void   (*ctx_SwitchEnter)();    /* address of the library function */
  60.         UWORD    ctx_LaunchInst;            /* jsr Abs.l */
  61.         void   (*ctx_LaunchEnter)();    /* ditto */
  62. }
  63.  
  64. Thus, the actual switch/launch code of the task is part of the context 
  65. structure. This, together with the magic cookie above allows identification
  66. of the context of the task with only the task pointer given. The library code
  67. on the other hand should remove the dummy return address of the jsr, subtract
  68. the offset of the ctx_Switch field from this address and gets, by this magic,
  69. a pointer to the Context data structure. The further code should extract
  70. the MMU user root pointer from this structure, compare it with the already
  71. active root pointer and install the new pointer and flush the ATC of the MMU
  72. if required.
  73.  
  74. The tc_Switch entry has to call a routine that installs the common context
  75. root pointer, the tc_Launch entry has to install the private root pointer
  76. of the task. This has the advantage that we don't have to set the switch and
  77. launch entries of tasks not participating in the virtual memory buisiness,
  78. but the disadvantage that the MMU root pointer is set twice if a context
  79. switch to a task sharing the same context occurs. I've currently no idea
  80. how to fix this, but I guess the overhead of reloading the ATC isn't that
  81. big on the other hand.
  82.  
  83.     Exception handling
  84.  
  85. The mmu library should install its own bus error exception vector in the
  86. exception vector offsets. On a bus error, the following should happen:
  87.  
  88. -    First, check if its a long word access to AbsExecBase. If so, run the
  89.     specific emulator code of the processor. That's either trivial or tricky:
  90.  
  91.     For the '020 or '030, fill the input queue in the stack frame with the
  92.     correct value, set some bits in the exception stack frame and continue
  93.     execution.
  94.  
  95.     For the '040, check if some writes are still in the pipeline. If so, run
  96.     the magic part, see below. If not, try first to decode the instruction
  97.     manually. If it's an move.l AbsExecBase.w,a6 or a move.l AbsExecBase.l,a6,
  98.     emulate it by software, adjust the exception stack frame and continue
  99.     execution.
  100.  
  101.     For the '060, the exception model is much simpler. There's no write 
  102.     pipeline and we can basically use the same technique as above.
  103.  
  104.     And now for the tricky part: 
  105.  
  106.     Emulation of the instruction access for the '040 and '060 if the 
  107.     instruction cannot decoded manually. This means that we've to turn off
  108.     the protection of AbsExecBase, turn on tracing, execute the instruction
  109.     in trace mode and turn on the protection afterwards. This means, too,
  110.     that we might need to patch some Cache related calls of the exec.library.
  111.     Urgh! Details of this method can be found in the enforcer code and the
  112.     CyberGuard. At least, this kind of magic does already work.
  113.  
  114. -    If the access is NOT an access of AbsExecBase, then check the
  115.     reason for the exception. 
  116.  
  117.     If it is not caused by the MMU, select the bus error handler list
  118.     for the next step.
  119.  
  120.     If it is caused by the MMU, get the context of the task that caused 
  121.     the exception by investigating its tc_Switch and tc_Launch fields. 
  122.     If no context can be found, then get the global common context.
  123.  
  124.     Check, in this context, the status of that address. If it is marked
  125.     as invalid, or write protected and the access is a write access, or
  126.     as supervisor only, and the task is in user state, then use the
  127.     segmentation fault list for the next step. A future version of the 
  128.     enforcer might set this hook and may print out some useful 
  129.     information about the crash.
  130.  
  131.     If the status of the address is "swapped", use the "swapped fault"
  132.     list of the context. This points, too, by default, to a routine that
  133.     calls the exception handler of the task. 
  134.  
  135. -     In the next step, check all handlers on the hook list, sorted by
  136.     priority. Check for each hook if it applies to all tasks (the task
  137.     field is NULL in this case), or if it applies to this task. In
  138.     this case, build the ExceptionData structure on the stack, partially
  139.     using information from the exception stack frame (esp. the return
  140.     PC is useful here) and call the exception interrupt, by loading
  141.     the registers as pointed out in the autodocs. If the handler returns
  142.     0, it was able to handle the exception and the MMU lib will simply
  143.     continue with RTE, hoping that the handler modified the exception
  144.     stack frame appropriately. 
  145.  
  146. -    Check the exception data structure and the EXDF_CONTINUE flag.
  147.     If that flag is not set, the CPU is allowed to rerun the faulty
  148.     instruction (that's the easy case for the '060 and the most
  149.     useful for the use of the memory.library).
  150.  
  151.     If the flag IS set, things become rather tricky.
  152.  
  153.     The mmu table must be modified temporarily to point to a "spare page"
  154.     somewhere in memory. The value to be read must be set to the right
  155.     position within this spare page, tracing must be enabled and
  156.     the faulty instruction must be traced over. It will now read the
  157.     word from the spare page we placed there, by using the modified
  158.     MMU table.
  159.     The trace exception will now occur - we then may restore the MMU
  160.     table, disable tracing and continue the program. 
  161.     This is, indeed, very tricky. Especially the interaction with
  162.     DMA is worth a lot of consideration, check the enforcer code
  163.     for details how this magic can be done. Urgh.
  164.  
  165. The message hooks:
  166.  
  167.     This is a tricky handler mechanism that builds on top of the
  168.     hook mechanism pointed out above, but is somewhat more sophisticated
  169.     and designed for the use of the memory library.
  170.  
  171.     A message hook will install a context hook of the kind described
  172.     above. The hook function will then:
  173.  
  174.     -check wether task switching is enabled or not. If it's not, it
  175.      cannot perform its operation and will return with -1 - the
  176.      next handler of the exception chain will be called then.
  177.     -"Bend" the return PC to its own function and keep the original
  178.      return PC in the message hook structure,
  179.     - copy the exception data to the exception message embedded
  180.  
  181.     resume operation afterwards.
  182.  
  183.     The faulty task will then continue execution of the message
  184.     exception handler of the mmu.library. This function will now 
  185.     send the build message to the port indicated in the exception hook
  186.     data and will, furthermore, wait for return of the message on the
  187.     reply port which is embedded in the hook data as well. Since I
  188.     don't want to spend a user signal for this, I'll have to use
  189.     an undocumented system signal for this port (yuk!)
  190.  
  191.     If the message returns, get the return PC from the message data
  192.     (which might be modified again by the task that received that
  193.     message), reload all registers and continue execution of the user
  194.     program.
  195.  
  196. The memory library:
  197.  
  198. CreateAdrSpace has basically to call CreateContext() of the mmu.library,
  199. and has to install its own swapped hook into that context. This will be
  200. simply a message hook of the type above with the port set to the global
  201. port of the swapper daemon.
  202.  
  203. o) The swapper daemon uses the logical address and the context to determinate
  204. the location of the swapped out page on disk, either in a file or in a
  205. disk partition. The details HOW the swapped blocks are kept on disk have still
  206. to be worked out, as well as the algorithm of which pages are swapped.
  207.  
  208. This means in detail:
  209.     - Try to allocate a physical memory block for the page. If that fails,
  210.     swap out another page and mark it invalid. Then use this page.
  211.  
  212.     - Read the data from disk.
  213.  
  214.     - Reply the message which was build by the library code.
  215.  
  216. o) The user code can now safely clean up the stack and retry the instruction
  217. that caused the exception.
  218.  
  219.